//此go文件为重要逻辑文件,尽量不要改动
//除了 如果增加新方法之外 需改动 ModelCRUD 之外 其余的一律不准改动

package models

import (
	"errors"
	"fmt"
	"go.uber.org/zap"
	"gorm.io/gorm"
	loggers "huijing_mall/pkg/logger"
	"reflect"
	"sync"
)

// ModelCRUD 通用CRUD接口，所有model需实现这些方法
type ModelCRUD interface {
	// Create 新增记录
	Create(db *gorm.DB) error

	// Update 更新记录（根据ID）
	Update(db *gorm.DB) error

	// Delete 根据ID删除记录
	Delete(db *gorm.DB, id uint) error

	// GetByID 根据ID查询记录
	GetByID(db *gorm.DB, id uint) error

	// GetByField  根据某个字段查询记录
	GetByField(db *gorm.DB, field string, value interface{}) error

	// List 查询列表（支持分页）
	List(db *gorm.DB, page, pageSize int) ([]interface{}, int64, error)

	// FindByRawSQL 自定义 sql 查询
	FindByRawSQL(db *gorm.DB, query string, args ...interface{}) error
}

// 原有的 modelCreator 不变（创建模型实例的函数）
type modelCreator func() ModelCRUD

// ModelRegInfo 表示单个模型的“注册信息”（类型+创建函数）
type ModelRegInfo struct {
	Type    ModelType    // 模型类型（如 UserType）
	Creator modelCreator // 模型的创建函数
}

// 全局映射表和读写锁（不变）
var (
	modelMap = make(map[ModelType]modelCreator)
	mu       sync.RWMutex
)

// RegisterModels 批量注册模型：接收 ModelRegInfo 切片，循环注册所有模型
// 用法类似 AutoMigrate(&User{}, &Product{})，这里是 RegisterModels([]ModelRegInfo{...})
func RegisterModels(regs []ModelRegInfo) {
	mu.Lock()
	defer mu.Unlock()

	// 循环处理每个模型的注册信息
	for _, reg := range regs {
		// 检查是否重复注册
		if _, exists := modelMap[reg.Type]; exists {
			panic(fmt.Sprintf("模型类型 %v 已注册，避免重复注册", reg.Type))
		}
		// 注册：将“类型-创建函数”存入映射表
		modelMap[reg.Type] = reg.Creator
	}
}

// （可选）保留单个注册函数，兼容零散注册场景
func RegisterModel(t ModelType, creator modelCreator) {
	// 直接调用批量注册函数，简化代码
	RegisterModels([]ModelRegInfo{{Type: t, Creator: creator}})
}

// NewModelCRUD 动态工厂函数：通过查询映射表创建模型实例
func NewModelCRUD(t ModelType) ModelCRUD {
	mu.RLock()
	defer mu.RUnlock()

	// 从映射表中获取该类型对应的创建函数
	creator, exists := modelMap[t]
	if !exists {
		return nil // 或返回默认错误
	}

	// 调用创建函数，返回模型实例（已实现 ModelCRUD 接口）
	return creator()
}

// AssertModelCRUD 泛型版：直接返回 targetModel 对应的指针类型（如 *Product）
// T: 泛型约束，必须是“实现 ModelCRUD 的模型指针”（如 *Product、*User）
func AssertModelCRUD[T ModelCRUD](crud ModelCRUD) (T, error) {
	// 1. 校验 crud 实例是否为指针类型
	crudType := reflect.TypeOf(crud)
	if crudType == nil || crudType.Kind() != reflect.Ptr {
		return *new(T), errors.New("ModelCRUD 实例必须是指针类型")
	}

	// 2. 校验 crud 真实类型是否与泛型 T 匹配
	// 先创建一个 T 类型的空实例（如 *Product），获取其类型
	var target T
	targetType := reflect.TypeOf(target)
	if crudType != targetType {
		return *new(T), fmt.Errorf(
			"类型不匹配：ModelCRUD 实例是 %T，目标模型是 %s",
			crud, targetType.Elem().Name(),
		)
	}

	// 3. 断言成功，直接转换为 T 类型（泛型已确保类型匹配）
	return crud.(T), nil
}

func InitAutoMg(DB *gorm.DB) error {
	//数据源 模型列表
	for _, m := range ModelToRegister {
		if err := DB.AutoMigrate(m.Creator()); err != nil {
			// 优化日志：补充"业务影响"（如"数据库自动迁移失败，可能导致功能不可用"），便于排查
			loggers.Error("数据库自动迁移失败", zap.Error(err), zap.Int("模型总数", len(ModelToRegister))) // 补充元数据，辅助定位问题

			return err // 补充错误返回，让上层感知失败（原函数无返回，失败后无法向上传递）
		}
	}
	loggers.Info("数据库自动迁移成功", zap.Int("模型总数", len(ModelToRegister)))
	return nil

}

// NewModelCRUD 工厂函数：根据类型创建对应的ModelCRUD实例
//func NewModelCRUD(t ModelType) ModelCRUD {
//	switch t {
//	case UserType:
//		return &models.User{} // 返回User结构体的指针（实现了ModelCRUD接口）
//	case ProductType:
//		return &models.Product{} // 返回Product结构体的指针
//	// 新增其他model的case...
//	default:
//		return nil
//	}
//}

// ========================================================================================

// 查询指定字段 Boss模型的结构体
type SelectBoss struct {
	JobName        string `gorm:"column:job_name"`         // 工作名称
	CityName       string `gorm:"column:city_name"`        // 城市名称
	JobDegree      string `gorm:"column:job_degree"`       // 文凭
	JobExperience  string `gorm:"column:job_experience"`   // 工作经验
	Address        string `gorm:"column:address"`          // 地址
	SalaryDesc     string `gorm:"column:salary_desc"`      // 薪资
	BossName       string `gorm:"column:boss_name"`        // 招聘人
	BossTitle      string `gorm:"column:boss_title"`       // 招聘人职位
	BrandName      string `gorm:"column:brand_name"`       // 招聘公司名称
	BrandScaleName string `gorm:"column:brand_scale_name"` // 公司规模
	BrandIndustry  string `gorm:"column:brand_industry"`   // 公司类型
	BrandStageName string `gorm:"column:brand_stage_name"` // 公司现状
	WelfareList    string `gorm:"column:welfare_list"`     // 公司福利
	Zwms           string `gorm:"column:zwms"`             // 职位描述
	GwZz           string `gorm:"column:gwzz"`             // 岗位职责
}

// TableName 自定义表名
func (b *SelectBoss) TableName() string {
	return "boss"
}
